﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using JBeamLibrary.Tools;

namespace DriveBeamEditor.Controls.General
{
    public partial class CommandButton : Button
    {
        #region Fields

        private Func<object, object> _command = obj => obj;
        private Color _hoverColor = Color.FromArgb(230, 231, 232);
        private Color _downColor = Color.FromArgb(88, 103, 104);
        private bool _mouseDown;
        private bool _mouseIn;

        public event EventHandler CommandChanged;
        public event EventHandler FireCommand;

        #endregion

        #region Properties

        /// <summary>Determines the command that will be executed when the button is pressed</summary>
        public Func<object, object> Command
        {
            get { return _command; }
            set
            {
                if (_command == value) return;
                _command = value;
                OnCommandChanged();
            }
        }

        /// <summary>Gets or sets the parameter to pass to the command</summary>
        [Category("Actions")]
        public object CommandParameter
        {
            get;
            set;
        }

        /// <summary>Gets or sets the backcolor when the button is hovered</summary>
        [Category("Appearance")]
        public Color BackColorHover
        {
            get { return _hoverColor; }
            set
            {
                _hoverColor = value;
                Invalidate();
            }
        }

        /// <summary>Gets or sets the backcolor when the button is down</summary>
        [Category("Appearance")]
        public Color BackColorDown
        {
            get { return _downColor; }
            set
            {
                _downColor = value;
                Invalidate();
            }
        }

        #endregion

        #region CTORs

        public CommandButton()
        {
            InitializeComponent();
            SetStyle(
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.Opaque |
                ControlStyles.CacheText |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.ResizeRedraw |
                ControlStyles.UserPaint, true
            );
        }

        #endregion

        #region Methods

        protected virtual void OnCommandChanged()
        {
            if (CommandChanged != null)
                CommandChanged(this, new EventArgs());
        }

        protected virtual void OnFireCommand()
        {
            if (FireCommand != null)
                FireCommand(this, new EventArgs());

            if (Command != null)
                Command(CommandParameter);
        }

        #endregion

        #region Overrides

        protected override void OnClick(EventArgs e)
        {
            OnFireCommand();
            base.OnClick(e);
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            _mouseIn = true;
            Invalidate();
            base.OnMouseEnter(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            _mouseIn = false;
            Invalidate();
            base.OnMouseLeave(e);
        }

        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            _mouseDown = true;
            Invalidate();
            base.OnMouseDown(mevent);
        }

        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            _mouseDown = false;
            Invalidate();
            base.OnMouseUp(mevent);
        }

        protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent);

            var color = _mouseIn ? _mouseDown ? _downColor : _hoverColor : BackColor;
            var rect = ClientRectangle;
            var brush = new SolidBrush(color);

            pevent.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            pevent.Graphics.FillRectangle(brush, rect);
        }

        #endregion
    }
}
